"""
Public blueprint for unauthenticated routes.

Routes:
- GET / : Homepage with documentation list
- GET /docs/<int:id> : View single documentation
"""
from flask import Blueprint, render_template, abort, request, session, redirect, url_for, flash
from sqlalchemy import func
import markdown
import bleach

from app.models import Documentation

public_bp = Blueprint('public', __name__)

# Allowed HTML tags for Bleach sanitization
ALLOWED_TAGS = list(bleach.sanitizer.ALLOWED_TAGS) + [
    'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
    'code', 'pre', 'blockquote', 'ul', 'ol', 'li',
    'strong', 'em', 'a', 'img', 'table', 'thead', 'tbody', 'tr', 'th', 'td',
    'br', 'hr', 'span', 'div'
]

ALLOWED_ATTRIBUTES = {
    'a': ['href', 'title', 'target'],
    'img': ['src', 'alt', 'title', 'width', 'height'],
    'code': ['class'],  # For syntax highlighting
    'span': ['class'],
    'div': ['class'],
    'table': ['class'],
    'th': ['scope'],
}


def render_content(content, format_type):
    """
    Render documentation content based on format type.

    Args:
        content (str): Raw content string
        format_type (str): Format type ('markdown', 'html', 'text')

    Returns:
        str: Rendered HTML (safe for display)
    """
    if format_type == 'markdown':
        # Render Markdown to HTML
        html = markdown.markdown(
            content,
            extensions=['fenced_code', 'tables', 'nl2br']
        )
        # Sanitize HTML to prevent XSS
        return bleach.clean(html, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES)

    elif format_type == 'html':
        # Sanitize user-provided HTML
        return bleach.clean(content, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES)

    elif format_type == 'text':
        # Plain text: escape HTML and wrap in <pre>
        escaped = bleach.clean(content, tags=[], strip=True)
        return f'<pre style="white-space: pre-wrap; font-family: monospace;">{escaped}</pre>'

    else:
        # Unknown format: treat as plain text
        return render_content(content, 'text')


@public_bp.route('/')
def index():
    """
    Homepage: Display list of all published documentation.

    Returns:
        Rendered template with documentation list ordered by creation date (newest first)
    """
    # Get category filter from query string
    category_filter = request.args.get('category')

    # Get all unique categories for sidebar
    categories = Documentation.query.with_entities(
        Documentation.category
    ).filter(
        Documentation.category.isnot(None)
    ).group_by(Documentation.category).all()

    categories = [c[0] for c in categories if c[0]]  # Extract category names

    # Query documentation - show all for display, including locked ones with icon
    query = Documentation.query
    if category_filter:
        query = query.filter(Documentation.category == category_filter)

    documents = query.order_by(Documentation.created_at.desc()).all()

    # Check if user is admin
    is_admin = 'admin_id' in session

    return render_template(
        'public/index.html',
        documents=documents,
        categories=categories,
        current_category=category_filter,
        is_admin=is_admin
    )


@public_bp.route('/docs/<int:id>')
def view_document(id):
    """
    View single documentation entry.

    Args:
        id (int): Documentation ID

    Returns:
        Rendered template with documentation content

    Raises:
        404: If documentation with given ID doesn't exist
        Redirect to login: If document is locked and user is not admin
    """
    # Get documentation or return 404
    document = Documentation.query.get_or_404(id)

    # Check if document is locked and user is not admin
    is_admin = 'admin_id' in session
    if document.is_locked and not is_admin:
        flash('此文档已锁定，需要登录才能查看', 'error')
        return redirect(url_for('admin.login', next=request.url))

    # Render content based on format
    rendered_content = render_content(document.content, document.format)

    return render_template(
        'public/view.html',
        document=document,
        rendered_content=rendered_content
    )
